﻿using System;
using System.Linq;
using System.Reflection;
using Autofac;
using ShuttleBus.Subscriptions;
using Module = Autofac.Module;

namespace ShuttleBus.Config
{
    internal class ShuttleBusModule : Module
    {
        private readonly string _assemblyName;
        private readonly Func<Assembly, bool> _getReferencedAssemblies;

        internal ShuttleBusModule()
        {
            _assemblyName = GetType().Assembly.GetName().FullName;
            _getReferencedAssemblies = a =>
                                           {
                                               var referencedAssemblies1 = a.GetReferencedAssemblies();
                                               foreach (var referencedAssembly in referencedAssemblies1)
                                               {
                                                   if (referencedAssembly.FullName == _assemblyName)
                                                   {
                                                       return true;
                                                   }
                                                   continue;
                                               }
                                               return false;
                                           };
        }

        protected override void Load(ContainerBuilder builder)
        {
            var assemblies = AppDomain.CurrentDomain.GetAssemblies().Where(_getReferencedAssemblies).ToArray();

            builder.RegisterAssemblyTypes(assemblies)
                .Where(t =>
                       t.GetInterfaces()
                           .Where(type => type.IsGenericType)
                           .Any(type => type.GetGenericTypeDefinition().FullName == typeof(IHandle<>).FullName))
                .AsImplementedInterfaces()
                .OnActivated(a => a.Context.InjectUnsetProperties(a.Instance))
                .InstancePerLifetimeScope();

            builder.Register(c => new StreamReaderWrapper())
                .As<IReadStreams>()
                .InstancePerLifetimeScope();

            builder.Register(c => new StreamFactory())
                .As<ICreateStreams>()
                .InstancePerLifetimeScope();

            builder.Register(c => new TransportMessageFactory())
                .As<ICreateMessages>()
                .InstancePerLifetimeScope();

            builder.Register(c => new Bus(c.Resolve<ITransport>(),
                                          c.Resolve<ISubscriptionRepository>(),
                                          c.Resolve<ICreateMessages>()))
                .As<IBus>()
                .InstancePerDependency();

            builder.Register(c => new SubscriptionPublisher(c.Resolve<IBus>()))
                .As<IAddSubscriptions>()
                .InstancePerLifetimeScope();
        }
    }
}